package com.zhsource.article.service.impl;

import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zhsource.article.domain.ArticleType;
import com.zhsource.article.mapper.ArticleTypeMapper;
import com.zhsource.article.query.ArticleQuery;
import com.zhsource.article.query.ArticleTypeQuery;
import com.zhsource.article.service.IArticleTypeService;
import com.zhsource.constants.ArticleConstant;
import com.zhsource.tourist.vo.ArticleTypeCountVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * <p>@ClassName：ArticleTypeServiceImpl
 * <p>@Date 2023/10/17  13:01
 *
 * @Author zzl
 **/
@Slf4j
@Service
public class ArticleTypeServiceImpl implements IArticleTypeService {

    private static final ConcurrentHashMap<String, List<ArticleType>> articleTypeTreeMap = new ConcurrentHashMap<>();
    @Autowired
    private ArticleTypeMapper articleTypeMapper;

    @Autowired

    private RedisTemplate redisTemplate;

    @Override
    public List<ArticleType> list() {
        return articleTypeMapper.list();
    }

    @Override
    public ArticleType selectById(Long id) {
        return articleTypeMapper.selectById(id);
    }

    //    @Override
//    public PageResult<List<ArticleType>> page(ArticleTypeQuery articleTypeQuery) {
////        // 1.查询总条数
//        Integer total = articleTypeMapper.total(articleTypeQuery);
//        // 2.查询当前页数据
//        List<ArticleType> page = articleTypeMapper.page(articleTypeQuery);
//
//        return  new PageResult<>(total,page);
//
//    }
    @Override
    public PageInfo<ArticleType> page(ArticleTypeQuery articleTypeQuery) {
        // 1.下面这句代码表示开启分页，会将紧挨着这句代码的下一次数据库执行进行分页，切记一定要放在要分页的SQL语句前面执行
        PageHelper.startPage(articleTypeQuery.getCurrentPage(), articleTypeQuery.getPageSize());

        // 2.执行SQL语句带条件查询，SQL语句不需要进行分页
        List<ArticleType> page = articleTypeMapper.page(articleTypeQuery);
        // 3.将查询结果转换为PageInfo对象，PageInfo对象中有前端分页所需要的各种参数
        PageInfo<ArticleType> pageInfo = new PageInfo<>(page);
        // 4.响应总条数和分页信息
        return pageInfo;

    }


    @Override
    @CacheEvict(cacheNames = ArticleConstant.ARTICLE_TYPE_NAMES, key = ArticleConstant.ARTICLE_TYPE_CACHE_TREE)
    public void update(ArticleType articleType) {
        articleTypeMapper.update(articleType);
    }


    @Override
    @CacheEvict(cacheNames = ArticleConstant.ARTICLE_TYPE_NAMES, key = ArticleConstant.ARTICLE_TYPE_CACHE_TREE)
    public void insert(ArticleType articleType) {
        articleTypeMapper.insert(articleType);
    }

    @Override
    @CacheEvict(cacheNames = ArticleConstant.ARTICLE_TYPE_NAMES, key = ArticleConstant.ARTICLE_TYPE_CACHE_TREE)
    public void delete(Long id) {
        articleTypeMapper.delete(id);
    }

    @Override
    public void batchDel(List<Long> ids) {
        articleTypeMapper.batchDel(ids);
    }


//    /**
//     * @Description: 查询菜单树数据
//     * @Author: Neuronet
//     * @Date: 2023/10/24 15:13
//     * @Return:
//     **/
//    @Override
//    public List<ArticleType> tree() {
//        // 1.从而本地缓存中获取到文章类型数据
//        List<ArticleType> articleTypeTreeTmp = articleTypeTreeMap.get(ArticleConstant.ARTICLE_TYPE_TREE);
//        // 判断本地缓存中是否存在
//        if (ObjUtil.isEmpty(articleTypeTreeTmp)){
//            log.info("本地缓存不存在，请查询数据库！");
//            return  getArticleTypeTree();
//        }
//        log.info("本地缓存中存在，直接响应！");
//        // 3.有就直接响应
//        return articleTypeTreeTmp;
//    }
//
//    private List<ArticleType> getArticleTypeTree() {
//        // 1.查询所有菜单数据
//        List<ArticleType> articleTypes = articleTypeMapper.list();
//        // 2.准备一个空集合，放组装完成的树数据
//        List<ArticleType> articleTypeTree = new ArrayList<>();
//
//        Map<Long, ArticleType> typeMap = articleTypes.stream().collect(Collectors.toMap(ArticleType::getId, value -> value));
//
//        // 3.遍历集合，找一级以及子级进行组装
//        for (ArticleType articleType : articleTypes) {
//            // 3.1.如果parentId等于空，那么说明是顶级，就存入到新集合中
//            if (articleType.getParentId() == null){
//                articleTypeTree.add(articleType); // 注意：此处是地址值对象存储，不是深拷贝是浅拷贝
//            }else { // 3.2.如果它不是顶级，那么一定有父亲
//                // 1.再次遍历集合，去找当前外层循环这个对象的父级
//                ArticleType articleType1 = typeMap.get(articleType.getParentId());
//                if (!ObjUtil.isEmpty(articleType1)){
//                    articleType1.getChildren().add(articleType);
//                }
//
//            }
//        }
//        articleTypeTreeMap.put(ArticleConstant.ARTICLE_TYPE_TREE,articleTypeTree);
//        return articleTypeTree;
//    }

    /**
     * @Description: 查询菜单树数据
     * @Author: Neuronet
     * @Date: 2023/10/24 15:13
     * @Return:
     **/

    // 这个注解每次进入方法之前会根据你给定 的key去redis中查询，如果没有再进入，如果有则直接响应，方法都不进、
    // 查询到数据之后会自动帮你把数据存储到Redis中
    @Cacheable(cacheNames = ArticleConstant.ARTICLE_TYPE_NAMES,key = ArticleConstant.ARTICLE_TYPE_CACHE_TREE)
    @Override
    public List<ArticleType> tree() {
        return getArticleTypeTree();
         }



    @Override
    public List<ArticleTypeCountVo> getArticleTypeCount( ) {
        return articleTypeMapper.getArticleTypeCount();
    }

    private List<ArticleType> getArticleTypeTree() {
        // 1.查询所有菜单数据
        List<ArticleType> articleTypes = articleTypeMapper.list();
        // 2.准备一个空集合，放组装完成的树数据
        List<ArticleType> articleTypeTree = new ArrayList<>();

        Map<Long, ArticleType> typeMap = articleTypes.stream().collect(Collectors.toMap(ArticleType::getId, value -> value));
        // 3.遍历集合，找一级以及子级进行组装
        for (ArticleType articleType : articleTypes) {
            // 3.1.如果parentId等于空，那么说明是顶级，就存入到新集合中
            if (articleType.getParentId() == null) {
                articleTypeTree.add(articleType); // 注意：此处是地址值对象存储，不是深拷贝是浅拷贝
            } else { // 3.2.如果它不是顶级，那么一定有父亲
                // 1.再次遍历集合，去找当前外层循环这个对象的父级
                ArticleType articleType1 = typeMap.get(articleType.getParentId());
                if (!ObjUtil.isEmpty(articleType1)) {
                    articleType1.getChildren().add(articleType);
                }

            }
        }
        return articleTypeTree;
    }
}
